<?php
/**
 * 合成模式
 *
 * 使得客户对单个对象和对象容器的使用具有一致性。
 */
//相同结构的抽象类
abstract class AbstractClass
{
	//节点标识
	public $name;
	//节点结构
	public $list;
	//增加一个子节点
	abstract public function Add(AbstractClass $item);
	//删除一个子节点
	abstract public function Remove(AbstractClass $item);
	//打印节点
	abstract public function Output();
}
//枝干类
class Limb extends AbstractClass{
	public function __construct()
	{
		$this->list = array();
	}
	public function Add(AbstractClass $item){
		//构建一个只有当前节点的数组。
		$other_list = array($item);
		//获取交集
		$result_list = array_uintersect($this->list,$other_list,array(__CLASS__,"key_compare_func"));
		//如果节点不存在，添加节点。
		if(empty($result_list)){
			array_push($this->list,$item);
		}
	}
	public function Remove(AbstractClass $item){
		//构建一个只有当前节点的数组。
		$other_list = array($item);
		//获得原节点结构与当前节点结构的差集
		$result_list = array_udiff($this->list,$other_list,array(__CLASS__,"key_compare_func"));
		//将原先节点置为差集
		$this->list = $result_list;
	}
	//比较的方法
	public function key_compare_func($a,$b)
	{
		if(is_object($a)&&is_object($b)&&$a->name === $b->name){
			return 0;
		}
		return ($a > $b)? 1 :-1;
	}
	//输出节点
	public function Output()
	{
		var_dump($this);
	}
}
//叶子类
class leaf extends AbstractClass{
	public function __construct(){
		//叶子不存在子节点
		$this->list = null;
	}
	public function Add(AbstractClass $item){
		//叶子不能添加子节点
	}
	public function Remove(AbstractClass $item){
		//叶子不能删除子节点
	}
	public function Output()
	{
		var_dump($this);
	}
}
//创建名字为1的树
$tree = new Limb();
$tree->name = "1";
//给树添加叶子2
$leaf2 = new Leaf();
$leaf2->name = "2";
$tree->Add($leaf2);
//给树添加树枝3
$limb3 = new Limb();
$limb3->name = "3";
$tree->Add($limb3);
//给树枝3添加叶子4
$leaf4 = new Leaf();
$leaf4->name = "4";
$limb3->Add($leaf4);
//给树枝4添加叶子5
$leaf5 = new Leaf();
$leaf5->name = "5";
$limb3->Add($leaf5);
$limb3->Output();
//删除节点4
$limb3->Remove($leaf4);
//输出树
$limb3->Output();